package com.framework.service.yhbservice.impl;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.framework.dao.YHBDao.user.YhbUserDao;
import com.framework.entity.sys.SysBank;
import com.framework.entity.sys.SysDict;
import com.framework.entity.sys.SysPayment;
import com.framework.entity.ter.TerTerminalInfo;
import com.framework.exception.RRException;
import com.framework.exception.menu.RespCode;
import com.framework.page.PageUtils;
import com.framework.redis.util.RedisUtil;
import com.framework.service.*;
import com.framework.service.yhbservice.*;
import com.framework.utils.UuidUtil;
import com.framework.utils.pay.yunzhanghujiesuan.YunJieSuanPay;
import com.framework.utils.string.StringUtil;
import com.framework.utils.verified.Verified;
import com.framework.validator.Assert;
import com.framework.yhbEntity.activiy.YhbActivityInfo;
import com.framework.yhbEntity.currentcount.YhbCurrentCount;
import com.framework.yhbEntity.transaction.YhbFlowTake;
import com.framework.yhbEntity.user.*;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Transactional(rollbackFor = Exception.class)
@Service("yhbUserService")
public class YhbUserServiceImpl extends ServiceImpl<YhbUserDao, YhbUser> implements YhbUserService {


    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private DictService dictService;
    @Autowired
    private YhbPhoneDepotService yhbPhoneDepotService;
    @Autowired
    private YhbUserTerminalRelationService yhbUserTerminalRelationService;
    @Autowired
    private TerminalInfoService terminalInfoService;
    @Autowired
    private YhbUserBankService yhbUserBankService;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private YhbCusTerService yhbCusTerService;
    @Autowired
    private YhbFlowTakeService yhbFlowTakeService;
    @Autowired
    private YhbAddreesService yhbAddreesService;

    @Autowired
    private YhbCurrentCountService yhbCurrentCountService;

    @Autowired
    private AgentService agentService;


    @Override
    public YhbUser queryUserByPhone(String phone, Long deptId) {
        YhbUser u = new YhbUser();
        u.setPhone(phone);
        u.setDeptId(deptId);
        return baseMapper.selectOne(u);
    }

    @Override
    public Map<String, Object> login(String phone, Long deptId, String smsCode) {
        Assert.isBlank(phone, "手机号不能为空");
        Assert.isBlank(smsCode, "验证码不能为空");
        if (deptId == null) {
            throw new RRException("9000", "用户宝不能为空");
        }
        //获取登录短信类型
        SysDict sysDict = dictService.querySysDict("login", "sms_type");
        if (sysDict == null) {
            throw new RRException("9000", "错误的短信类型");
        }
        String key = sysDict.getValue() + phone;

        if(!"111111".equals(smsCode)){
            boolean isExist = redisUtil.hasKey(key);
            if (!isExist) {
                throw new RRException("9000", "验证码不存在或者已经失效");
            }
            String logCode = (String) redisUtil.get(key);
            if (!StringUtils.equals(smsCode, logCode)) {
                throw new RRException("9000", "验证码不正确");
            }
        }



        Map<String, Object> map = new HashMap<>();
        YhbUser user = queryUserByPhone(phone, deptId);
        if (user != null) {
            String token = UuidUtil.getUUID();
            redisUtil.set(token, phone + "-" + deptId, RedisUtil.LOGIN_EXPIRATION_TIME);
            redisUtil.set(phone + "-" + deptId, user, RedisUtil.LOGIN_EXPIRATION_TIME);

            map.put("success", true);
            map.put("user", user);
            map.put("token", token);
        } else {
            map.put("success", false);
            YhbPhoneDepot pd = yhbPhoneDepotService.queryByPhone(phone);
            if (pd==null){
                YhbPhoneDepot phoneDepot = new YhbPhoneDepot();
                phoneDepot.setPhone(phone);
                phoneDepot.setIsUser(0);
                phoneDepot.setCreateDate(new Date());
                yhbPhoneDepotService.insert(phoneDepot);
            }

            YhbCusTer cusTer = yhbCusTerService.queryInfoByPhone(phone,deptId);
            if(cusTer!=null){
                map.put("hasCus",true);
                map.put("cusTer",cusTer);
            }else {
                map.put("hasCus",false);
            }

        }
        return map;
    }

    @Override
    public Map<String, Object> getUserByToken(String token) {
        Map<String, Object> map = new HashMap<>();
        Object phoneObj = redisUtil.get(token);
        if (phoneObj == null) {
            throw new RRException("0010","账户已安全退出,请重新登录");
        }
        String str = (String) phoneObj;
        YhbUser user= (YhbUser) redisUtil.get(str);
        YhbUser curUser = baseMapper.selectById(user.getUserId());
        if(curUser==null){
            throw new RRException("0010","账户已安全退出,请重新登录");
        }
        map.put("user",curUser);
        map.put("noidentity",user.getIdentity()==null || "".equals(user.getIdentity()));
        map.put("notradePassword",user.getTradePassword()==null || "".equals(user.getTradePassword()));
        return map;
    }

    @Override
    public Map<String, Object> registUser(String phone, Long deptId, String sn, String username) {
        Assert.isBlank(phone, "手机号码不能为空");

        YhbUser user = queryUserByPhone(phone, deptId);
        if (user != null) {
            throw new RRException("9000", "该手机号码已注册");
        }
        BigDecimal initalAmount = new BigDecimal("10.00");
        YhbUser regUser = new YhbUser();
        String userId=StringUtil.getDateString(5);
        userId=infoUserId(userId);
        regUser.setDeptId(deptId);
        regUser.setAvailableAmount(initalAmount);
        regUser.setTotalAmount(initalAmount);
        regUser.setTotalTrade(new BigDecimal("0.00"));
        regUser.setPhone(phone);
        regUser.setUsername(username);
        regUser.setUserId(userId);
        regUser.setCreateDate(new Date());
        regUser.setFreezenAmount(initalAmount);
        String userNo="8"+StringUtil.getRandomNumberString(9);
        String currUserNo=infoUserNo(userNo);
        regUser.setUserNo(currUserNo);
        baseMapper.insert(regUser);
        YhbUser tempUser = queryUserByPhone(phone, deptId);
        if (tempUser == null) {
            throw new RRException("9000", "注册失败");
        }
        YhbUserTerminalRelation trs = yhbUserTerminalRelationService.queryRelationBySn(sn);
        if(trs!=null){
            if (!trs.getUserId().equals(tempUser.getUserId())){
                throw new RRException("9000","该终端已被绑定");

            }
        }
        YhbUserTerminalRelation relation=new YhbUserTerminalRelation();
        relation.setSn(sn);
        relation.setCreateDate(new Date());
        relation.setUserId(tempUser.getUserId());
        relation.setIsUse(1);
        yhbUserTerminalRelationService.insert(relation);

        TerTerminalInfo t = terminalInfoService.queryTerminalBySn(sn);
        if(t==null){
            throw new RRException("9000","未查询到终端信息");
        }
        t.setIsYhbuse(1);
        terminalInfoService.updateById(t);

        YhbPhoneDepot y = yhbPhoneDepotService.queryByPhone(phone);
        if(y!=null){
            yhbPhoneDepotService.updateIsUser(phone);
        }else {
            YhbPhoneDepot phoneDepot=new YhbPhoneDepot();
            phoneDepot.setCreateDate(new Date());
            phoneDepot.setIsUser(1);
            phoneDepot.setPhone(phone);
            yhbPhoneDepotService.insert(phoneDepot);
        }
        Map<String,Object> map=new HashMap<>();
        String token = UuidUtil.getUUID();
        redisUtil.set(token, phone + "-" + deptId, RedisUtil.LOGIN_EXPIRATION_TIME);
        redisUtil.set(phone + "-" + deptId, tempUser, RedisUtil.LOGIN_EXPIRATION_TIME);

        map.put("user", tempUser);
        map.put("token", token);

        //添加注册奖励流水
        yhbCurrentCountService.addRegisterCount(userId);

        //核实手机号是否有相关地址
        YhbUserAddress address = yhbAddreesService.queryAddressByPhone(phone);
        //不为空则绑定
        if(address!=null){
            address.setUserId(userId);
            yhbAddreesService.updateById(address);
        }

        return map;
    }

    public String infoUserNo(String userNo) {
        Assert.isBlank(userNo,"账户号不能为空");
        YhbUser user=new YhbUser();
        user.setUserNo(userNo);
        YhbUser temp = baseMapper.selectOne(user);
        if(temp!=null){
            userNo="8"+StringUtil.getRandomNumberString(9);
            infoUserNo(userNo);
        }

        return userNo;
    }

    @Override
    public YhbUser queryUserByToken(String token) {
        if(StringUtil.isEmpty(token)){
            throw  new RRException(RespCode.ERROR_TOKEN);
        }
        String str= (String) redisUtil.get(token);
        if(str==null){
            throw  new RRException(RespCode.JWT_ERRCODE_EXPIRE);
        }
        YhbUser user= (YhbUser) redisUtil.get(str);
        /*String[] strs = str.split("-");
        user=queryUserByPhone(strs[0],Long.valueOf(strs[1]));*/
        if(user==null){
            throw  new RRException(RespCode.JWT_ERRCODE_EXPIRE);
        }
        return user;
    }

    @Override
    public void updateHeadImg(String token, String headImg) {
        YhbUser user = queryUserByToken(token);
        user.setHeadImg(headImg);
        baseMapper.updateById(user);
        YhbUser updatedUser = baseMapper.selectById(user.getUserId());
        String key= (String) redisUtil.get(token);
        redisUtil.set(key,updatedUser);
    }

    @Override
    public void setTradePassword(String token, String password, String confPassword) {
        Assert.isBlank(password,"交易密码不能为空");
        Assert.isBlank(confPassword,"确认密码不能为空");
        YhbUser user = queryUserByToken(token);
        if(!StringUtils.equals(password,confPassword)){
            throw  new  RRException("9000","两次密码不一致");
        }
        user.setTradePassword(password);
        baseMapper.updateById(user);
        YhbUser updatedUser = baseMapper.selectById(user.getUserId());
        String key= (String) redisUtil.get(token);
        redisUtil.set(key,updatedUser);

    }

    @Override
    public void updateTradePassword(String token, String password, String confPassword, String smsCode, String oldPassword) {
        YhbUser user = queryUserByToken(token);

        if(!user.getTradePassword().equals(oldPassword)){
            throw new RRException("9000","旧密码输入错误");
        }

        if(StringUtils.isBlank(smsCode)){
            throw new RRException(RespCode.NOT_PARAM_ERROR);
        }
        //校验验证码是否存在
        SysDict dict = dictService.querySysDict("u_pwd","sms_type");
        if(dict == null){
            throw new RRException("9000","未查询到设置的短信类型");
        }

        String bankValue = dict.getValue()+user.getPhone();
        boolean isCode = redisUtil.hasKey(bankValue);
        if(!isCode){
            throw new RRException("9000","验证码错误");
        }
        String resCode = (String)redisUtil.get(bankValue);
        if(!StringUtils.equals(resCode,smsCode)){
            throw new RRException("9000","验证码错误");
        }

        setTradePassword(token,password,confPassword);

        redisUtil.del(bankValue);
    }

    @Override
    public void takeMoney(String token, String takeAmount, String password, String yhbBankId) {
        YhbUser user = queryUserByToken(token);

        YhbUser currUser = baseMapper.selectById(user.getUserId());

        if(currUser.getTradePassword()==null || "".equals(currUser.getTradePassword())){
            throw new RRException("9002","提现密码为空");
        }

        if(!password.equals(currUser.getTradePassword())){
            throw new RRException("9000","提现密码错误");
        }

        YhbUserBank userbank = yhbUserBankService.selectById(yhbBankId);
        if(userbank==null){
            throw new  RRException("9000","未查询到银行卡信息");
        }

        Assert.isBlank(currUser.getIdentity(),"无身份证号,请补全信息");

        if((new BigDecimal("100").compareTo(currUser.getAvailableAmount())==1)){
            throw  new RRException("9000","提现时余额必须大于100元");
        }
        SysPayment payment = paymentService.queryPaymentByDeptId(currUser.getDeptId());
        if(payment==null){
            throw new RRException("9000","未查询到代付信息");
        }

        BigDecimal takeamount=new BigDecimal(takeAmount);
        int reslut=takeamount.compareTo(currUser.getAvailableAmount());
        if(reslut==1){
            throw new RRException("9000","可提余额不足");
        }
        int payType=payment.getPayType();
        String orderNo=StringUtil.getDateString(6);
        SysBank sysBank=new SysBank();
        sysBank.setBankNo(userbank.getBankNo());
        sysBank.setCardName(userbank.getCardName());

        //到账金额
        BigDecimal arrivalAmount=takeamount;
        //计算税率
        BigDecimal tax=takeamount.multiply(payment.getChargeRate()).divide(new BigDecimal("100"));
        //扣除税率
        arrivalAmount=arrivalAmount.subtract(tax);
        //扣除手续费
        arrivalAmount=arrivalAmount.subtract(payment.getChargeAmount());
        if(payType==4){
            Boolean flag = YunJieSuanPay.queryAccountAmount(takeAmount, payment);
            if(flag){
                throw new RRException("9000","当前提现人员过多,请稍后再试");
            }

            YunJieSuanPay.yunJieSuanPay(orderNo,sysBank,user.getIdentity(), String.valueOf(arrivalAmount),payment,"用户宝提现");
        }
        //添加提现记录
        YhbFlowTake yhbFlowTake=new YhbFlowTake();
        //设置提现金额
        yhbFlowTake.setTakeAmount(takeamount);
        //到账金额
        yhbFlowTake.setArrivalAmount(arrivalAmount);
        //提现钱金额
        yhbFlowTake.setCurrAvailableAmount(currUser.getAvailableAmount());
        //提现后金额
        yhbFlowTake.setCurrAftertakeAmount(currUser.getAvailableAmount().subtract(takeamount));
        yhbFlowTake.setTakeState("EXAMINE");
        yhbFlowTake.setExplain("提现审核中");
        yhbFlowTake.setUserId(user.getUserId());
        yhbFlowTake.setYhbTakeNo(orderNo);
        yhbFlowTake.setTakeTime(new Date());
        yhbFlowTake.setDeptId(user.getDeptId());
        yhbFlowTake.setTakeType(4);
        yhbFlowTakeService.insert(yhbFlowTake);
        //修改金额
        reduceAmount(currUser.getUserId(),takeAmount);
        //重新查询
        currUser=selectById(currUser.getUserId());
        //刷新缓存
        String key= (String) redisUtil.get(token);
        redisUtil.set(key,currUser);

        //添加流水记录
        YhbCurrentCount yhbCurrentCount=new YhbCurrentCount();
        yhbCurrentCount.setCreateDate(new Date());
        yhbCurrentCount.setAmount(takeamount);
        yhbCurrentCount.setIncome(2);
        yhbCurrentCount.setIncomeType(2);
        yhbCurrentCount.setRelationId(orderNo);
        yhbCurrentCount.setUserId(user.getUserId());
        yhbCurrentCount.setIsActivity(0);
        yhbCurrentCount.setMoney(new BigDecimal("0"));
        yhbCurrentCount.setAccountId(StringUtil.getDateString(5));
        yhbCurrentCountService.insert(yhbCurrentCount);

    }

    public void reduceAmount(String userId, String takeAmount) {
        baseMapper.reduceAmount(userId,takeAmount);
    }

    @Override
    public void outLogin(String token) {
        redisUtil.del(token);
    }

    @Override
    public Map<String, Object> toTakePage(String token) {
        Map<String, Object> map = new HashedMap();
        YhbUser user = queryUserByToken(token);
        YhbUser yhbuser = selectById(user.getUserId());
        if (yhbuser.getState().intValue() == 3) {
            throw new RRException("9000", "提现暂被封禁,请联系客服");
        }
        Long deptId = yhbuser.getDeptId();
        String userId = yhbuser.getUserId();
        //默认银行卡信息
        YhbUserBank bank = yhbUserBankService.queryBankInfoByUserId(userId);



        if(bank==null){
            bank=yhbUserBankService.selectOneBank(userId);
            if(bank==null){
                map.put("code","9001");
            }else {
                yhbUserBankService.setDefault(bank.getYhbBankId());
                bank=yhbUserBankService.queryBankInfoByUserId(userId);
            }
        }
        map.put("bank", bank);
        //可提余额
        map.put("amount", yhbuser.getAvailableAmount());
        //手续费率
        SysPayment payment = paymentService.queryPaymentByDeptId(deptId);
        if (payment == null) {
            throw new RRException("9000", "未查询到代付配置信息");
        }
        if (payment.getState().intValue() == 2) {
            throw new RRException("9000", payment.getRemark());
        }

        map.put("minAmount", payment.getMinAmount());
        map.put("chargeAmount", payment.getChargeAmount());
        map.put("chargeRate", payment.getChargeRate() + "%");
        return map;
    }

    @Override
    public void forgetTradePassword(String token, String password, String confPassword, String smsCode) {
        YhbUser user = queryUserByToken(token);

        if(StringUtils.isBlank(smsCode)){
            throw new RRException(RespCode.NOT_PARAM_ERROR);
        }
        //校验验证码是否存在
        SysDict dict = dictService.querySysDict("t_forget","sms_type");
        if(dict == null){
            throw new RRException("9000","未查询到设置的短信类型");
        }

        String bankValue = dict.getValue()+user.getPhone();
        boolean isCode = redisUtil.hasKey(bankValue);
        if(!isCode){
            throw new RRException("9000","验证码错误");
        }
        String resCode = (String)redisUtil.get(bankValue);
        if(!StringUtils.equals(resCode,smsCode)){
            throw new RRException("9000","验证码错误");
        }

        setTradePassword(token,password,confPassword);

        redisUtil.del(bankValue);
    }

    @Override
    public void updateIdentity(YhbUser user, String identity) {
        //身份证验证
        Verified.verfiedIDCard(user.getUsername(), identity);
        user.setIdentity(identity);
        baseMapper.updateById(user);
    }

    @Override
    public void updateIdentityByToken(String token, String identity, String smsCode) {
        YhbUser user = queryUserByToken(token);
        if(StringUtils.isBlank(smsCode)){
            throw new RRException(RespCode.NOT_PARAM_ERROR);
        }
        //校验验证码是否存在
        SysDict dict = dictService.querySysDict("u_identity","sms_type");
        if(dict == null){
            throw new RRException("9000","未查询到设置的短信类型");
        }

        String bankValue = dict.getValue()+user.getPhone();
        boolean isCode = redisUtil.hasKey(bankValue);
        if(!isCode){
            throw new RRException("9000","验证码错误");
        }
        String resCode = (String)redisUtil.get(bankValue);
        if(!StringUtils.equals(resCode,smsCode)){
            throw new RRException("9000","验证码错误");
        }
        updateIdentity(user,identity);
        //刷新缓存
        String key= (String) redisUtil.get(token);
        YhbUser u = selectById(user.getUserId());
        redisUtil.set(key,u);
    }

    @Override
    public List<Map<String, Object>> queryOwnerBySn(String token) {
        YhbUser user = queryUserByToken(token);
        return baseMapper.queryOwnerBySn(user.getUserId());
    }

    @Override
    public YhbUser addNewUser(YhbCusTer yct) {

        YhbUser user=queryUserByPhone(yct.getPhone(),yct.getDeptId());

        if(user!=null){
            throw new RRException("9000","该手机号已被注册");
        }

        String userId=StringUtil.getDateString(5);

        userId=infoUserId(userId);

        YhbUser regUser = new YhbUser();
        BigDecimal initalAmount=new BigDecimal("10");
        regUser.setDeptId(yct.getDeptId());
        regUser.setAvailableAmount(initalAmount);
        regUser.setTotalAmount(initalAmount);
        regUser.setTotalTrade(new BigDecimal("0.00"));
        regUser.setPhone(yct.getPhone());
        regUser.setUsername(yct.getUsername());
        regUser.setUserId(userId);
        regUser.setCreateDate(new Date());
        regUser.setFreezenAmount(initalAmount);
        String userNo="8"+StringUtil.getRandomNumberString(9);
        String currUserNo=infoUserNo(userNo);
        regUser.setUserNo(currUserNo);
        baseMapper.insert(regUser);
        //添加注册奖励流水
        yhbCurrentCountService.addRegisterCount(userId);

        return  selectById(userId);
    }

    @Override
    public YhbUser queryUserByUserId(String userId) {
        return baseMapper.selectById(userId);
    }

    @Override
    public void addAmount(YhbUser user, BigDecimal amount) {
        BigDecimal aviamount = user.getAvailableAmount();
        BigDecimal total=user.getTotalAmount();

        aviamount=aviamount.add(amount);
        total=total.add(amount);

        user.setTotalAmount(total);
        user.setAvailableAmount(aviamount);
        baseMapper.updateById(user);

    }

    @Override
    public void reduceBalance(String agId, BigDecimal totalAmount) {
        YhbUser user = queryUserByUserId(agId);
        BigDecimal aviamount = user.getAvailableAmount();

        aviamount=aviamount.subtract(totalAmount);

        user.setAvailableAmount(aviamount);
        baseMapper.updateById(user);

    }

    @Override
    public PageUtils queryUserList(Map<String, Object> params) {

        Integer currpage = Integer.valueOf(params.get("page").toString());
        Integer pageSize = Integer.valueOf(params.get("limit").toString());
        params.put("start", (currpage - 1) * pageSize);
        params.put("limit", pageSize);
        List<Map<String,Object>> list=baseMapper.queryUserList(params);
        Integer count=baseMapper.queryUserCount(params);
        return new PageUtils(list, count, pageSize, currpage);
    }


    @Override
    public void addBalance(String userId, BigDecimal takeAmount) {
        YhbUser user = queryUserByUserId(userId);

        BigDecimal availableAmount = user.getAvailableAmount();

        availableAmount=availableAmount.add(takeAmount);
        user.setAvailableAmount(availableAmount);
        baseMapper.updateById(user);
    }

    @Override
    public void rebackFrozenAmount(String userId, BigDecimal amount, String sn) {
        YhbUser user = queryUserByUserId(userId);
        BigDecimal freezen = user.getFreezenAmount();
        BigDecimal total=user.getTotalAmount();
        BigDecimal availableAmount = user.getAvailableAmount();
        total=total.add(amount);
        freezen=freezen.subtract(amount);
        availableAmount=availableAmount.add(amount);
        user.setFreezenAmount(freezen);
        user.setAvailableAmount(availableAmount);
        user.setTotalAmount(total);
        baseMapper.updateById(user);

        YhbCurrentCount cc=new YhbCurrentCount();

        cc.setUserId(userId);
        cc.setAmount(amount);
        cc.setMoney(amount);
        cc.setIsActivity(1);
        cc.setIncome(1);
        cc.setIncomeType(8);
        cc.setCreateDate(new Date());
        cc.setAccountId(StringUtil.getDateString(5));
        cc.setRelationId(sn);
        yhbCurrentCountService.insert(cc);

    }

    @Override
    public void frozenAmount(String sn, String userId, YhbActivityInfo yhbActivityInfo) {
        YhbUser yhbUser = queryUserByUserId(userId);

        BigDecimal freezenAmount = yhbUser.getFreezenAmount();
        freezenAmount=freezenAmount.add(yhbActivityInfo.getPayAmount());
        yhbUser.setFreezenAmount(freezenAmount);
        baseMapper.updateById(yhbUser);
        yhbUserTerminalRelationService.activSn(sn);
        YhbCurrentCount cc=new YhbCurrentCount();
        cc.setCreateDate(new Date());
        cc.setIncomeType(7);
        cc.setIncome(2);
        cc.setIsActivity(1);
        cc.setMoney(yhbActivityInfo.getPayAmount());
        cc.setAmount(yhbActivityInfo.getPayAmount());
        cc.setUserId(userId);
        String accountId=StringUtil.getDateString(5);

        cc.setAccountId(accountId);
        cc.setRelationId(yhbActivityInfo.getYhbActivityId().toString());
        yhbCurrentCountService.insert(cc);

        agentService.addYhbActivAmount(sn,yhbActivityInfo.getActivAmount());




    }

    private String infoUserId(String userId) {
        Assert.isBlank(userId,"账户id不能为空");

        YhbUser temp = baseMapper.selectById(userId);
        if(temp!=null) {
            userId = StringUtil.getDateString(5);
            infoUserId(userId);
        }
        return userId;

    }

}
